/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package presenter;

import analisador.LexicalError;
import analisador.Lexico;
import analisador.SemanticError;
import semantico.Semantico;
import analisador.Sintatico;
import analisador.SyntaticError;
import analisador.Token;
import java.io.*;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import model.TabelaSimbolo;
import presenter.TelaActionListeners.AbrirActionListener;
import presenter.TelaActionListeners.GravarActionListener;
import presenter.TelaActionListeners.GravarCodigoActionListener;
import presenter.TelaActionListeners.GravarComoActionListener;
import presenter.TelaActionListeners.NovoActionListener;
import presenter.TelaActionListeners.SairActionListener;
import presenter.TelaActionListeners.TabelaSimboloListener;
import presenter.TelaActionListeners.TelaCodigoListener;
import presenter.TelaActionListeners.VerificarActionListener;
import view.TelaCodigo;
import view.TelaGrafica;
import view.TelaTabelaSimbolo;
import view.TelaView;

/**
 * Controlador da de tela
 *
 * @author Devair
 */
public class TelaPresenter {

    private TelaView view;
    private TelaTabelaSimbolo viewSimbolo;
    private TelaCodigo viewCodigo;

    public TelaPresenter() {

        this.view = new TelaGrafica();
        this.viewSimbolo = new TelaTabelaSimbolo();
        this.viewCodigo = new TelaCodigo();
    }

    public TelaView getView() {

        return view;
    }

    public void setView(TelaView view) {
        this.view = (TelaView) view;
    }

    /**
     * Chama metodo de criacao da tela grafica
     */
    public void createView() {
        this.setUpViewListeners();
        view.packAndShow();
    }

    /**
     * Seta os listeners da tela grafica
     */
    public void setUpViewListeners() {

        view.addNovoActionListener(new NovoActionListener(this));
        view.addAbrirActionListener(new AbrirActionListener(this));
        view.addGravarActionListener(new GravarActionListener(this));
        view.addGravarComoActionListener(new GravarComoActionListener(this));
        view.addVerificarActionListener(new VerificarActionListener(this));
        view.addSairActionListener(new SairActionListener());
        view.addTabelaSimboloListener(new TabelaSimboloListener(this));
        view.addTelaCodigoListener(new TelaCodigoListener(this));
        viewCodigo.addGravarActionListener(new GravarCodigoActionListener(this) );

    }

    protected void abrirArquivo(File arquivo) throws FileNotFoundException, IOException {
        
              

        JFileChooser fileChoose = new JFileChooser();
        fileChoose.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChoose.setCurrentDirectory(arquivo);
        
        arquivo = null;
        
        FileNameExtensionFilter filter = new FileNameExtensionFilter("NEW J File", "njf");

        fileChoose.addChoosableFileFilter(filter);
        fileChoose.setFileFilter(filter);

        int ret = fileChoose.showOpenDialog(null);

        if (ret == JFileChooser.APPROVE_OPTION) {
            arquivo = fileChoose.getSelectedFile();

            if ((arquivo != null) && (arquivo.canRead())) {

                StringBuilder codigo = new StringBuilder();
                FileReader reader = new FileReader(arquivo);
                BufferedReader leitor = new BufferedReader(reader);

                String linha;

                while ((linha = leitor.readLine()) != null) {
                    codigo.append(linha.toString()).append("\n");
                }

                this.view.setArquivo(arquivo);
                this.view.setCodigo(codigo.toString());
            }
        }
    }

    protected void gravarArquivo(File arquivo, boolean novo) throws IOException {

        StringBuilder codigo = new StringBuilder(view.getCodigo());
        
        
        if ((arquivo == null) || novo) {

            JFileChooser fileChoose = new JFileChooser();
            fileChoose.setFileSelectionMode(JFileChooser.FILES_ONLY);
            fileChoose.setCurrentDirectory(arquivo);
            
            if (novo) {
                fileChoose.setDialogTitle("Gravar como...");
            } else {
                fileChoose.setDialogTitle("Gravar...");
            }

            FileNameExtensionFilter filter = new FileNameExtensionFilter("NEW J File (*.njf)", "njf");

            fileChoose.addChoosableFileFilter(filter);
            fileChoose.setFileFilter(filter);

            int ret = fileChoose.showSaveDialog(null);

            if (ret == JFileChooser.APPROVE_OPTION) {

                arquivo = fileChoose.getSelectedFile();

                if (arquivo != null) {

                    FileWriter fw = new FileWriter(arquivo+".njf");

                    fw.write(codigo.toString());

                    fw.flush();
                }
            }

        } else {

            FileWriter fw = new FileWriter(arquivo);
            fw.write(codigo.toString());
            fw.flush();
            fw.close();
        }

        this.view.setArquivo(arquivo);

    }

    protected void gravarArquivoCod(File arquivo, boolean novo) throws IOException {

        StringBuilder codigo = new StringBuilder(viewCodigo.getCodigo());
        
        
        if ((arquivo == null) || novo) {

            JFileChooser fileChoose = new JFileChooser();
            fileChoose.setFileSelectionMode(JFileChooser.FILES_ONLY);

            if (novo) {
                fileChoose.setDialogTitle("Gravar como...");
            } else {
                fileChoose.setDialogTitle("Gravar...");
            }

            FileNameExtensionFilter filter = new FileNameExtensionFilter("Assembly language souce file (*.asm)", "asm");

            fileChoose.addChoosableFileFilter(filter);
            fileChoose.setFileFilter(filter);

            int ret = fileChoose.showSaveDialog(null);

            if (ret == JFileChooser.APPROVE_OPTION) {

                arquivo = fileChoose.getSelectedFile();

                if (arquivo != null) {

                    FileWriter fw = new FileWriter(arquivo+".asm");

                    fw.write(codigo.toString());

                    fw.flush();
                    fw.close();
                }
            }

        } else {

            FileWriter fw = new FileWriter(arquivo);
            fw.write(codigo.toString());
            fw.flush();
        }

        this.viewCodigo.setArquivo(arquivo);
        

    }
    
    protected void novoArquivo() {        
        File file = new File("");
        this.view.setCodigo("");
        this.view.setMensage("");
        this.view.setArquivo(file);
        this.viewSimbolo.setTabelaSimbolo(new TabelaSimbolo());
    }

    public void novoArqCod() {
        File file = null;
        //this.viewCodigo.setCodigo("");
        //this.view.setMensage("");
        this.viewCodigo.setArquivo(file);
        
    }
    
    protected void analiseLexica() {
        String mensagem = "";

        Lexico lexico = new Lexico();
        lexico.setInput(view.getCodigo());

        try {
            Token t;
            while ((t = lexico.nextToken()) != null) {
                //System.out.println(t.getLexeme());
            }

        } catch (LexicalError e) {
            mensagem += (e.getMessage()) + "\n";
            //System.out.println(e.getMessage());
        }

        view.setMensage(mensagem);

    }

    protected void analiseSintatica() {

        String mensagem = "";

        Lexico lexico = new Lexico();
        Sintatico sintatico = new Sintatico();
        Semantico semantico = new Semantico();

        lexico.setInput(view.getCodigo());

        try {

            sintatico.parse(lexico, semantico);
            this.viewSimbolo.setTabelaSimbolo(semantico.getTabelaSimbolo());

            TabelaSimbolo tabela = semantico.getTabelaSimbolo();
            
            String codigo = semantico.getCodigo();
            this.viewCodigo.setCodigo("");
            this.viewCodigo.setCodigo(codigo);
            
            for (int i = 0; i < tabela.getRowCount(); i++) {
                if (!(boolean) tabela.getValueAt(i, 5)) {
                    if (("var".equals(tabela.getValueAt(i, 3).toString()))
                            || ("array".equals(tabela.getValueAt(i, 3).toString()))) {
                        throw new SemanticError("Variável declarada e não usada: " + tabela.getValueAt(i, 0), 0);
                    }
                }
            }

            
        } catch (LexicalError | SyntaticError | SemanticError e) {
            mensagem += e.getMessage() + "\n";
        }

        view.setMensage(mensagem);
    }

    protected void mostraTabelaSimbolos() {

        this.viewSimbolo.setVisible(true);

    }

    protected void mostraTelaCodigo() {

        this.getViewCodigo().setVisible(true);

    }
  

    /**
     * @return the viewCodigo
     */
    public TelaCodigo getViewCodigo() {
        return viewCodigo;
    }
}
